﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Data.Common;
using System.Configuration;

namespace JCSoft.Collect.Data
{
    public interface INHibernateRepository<T> : IDisposable
        where T : INHibernateRepository<T>
    {
        T AddOnSubmit(object o);
        T DeleteOnSubmit(object o);
        void SubmitChanges();
    }

    public class NHibernateRepository<T> : INHibernateRepository<T>
        where T : INHibernateRepository<T>
    {
        private ISession m_session;
        protected ISession Session
        {
            get
            {
                if (this.m_session == null)
                {
                    this.m_session = SessionFactory.CurrentFactory.OpenSession();
                    this.m_session.FlushMode = FlushMode.Never;
                }

                return this.m_session;
            }
        }

        private List<Action> m_changeActions;
        private List<Action> ChangeActions
        {
            get
            {
                if (this.m_changeActions == null)
                {
                    this.m_changeActions = new List<Action>();
                }

                return this.m_changeActions;
            }
            set
            {
                this.m_changeActions = value;
            }
        }

        public T AddOnSubmit(object o)
        {
            this.ChangeActions.Add(() => this.Session.Save(o));
            return (T)(INHibernateRepository<T>)this;
        }

        //public T UpdateOnSubmit(object o)
        //{
        //    this.ChangeActions.Add(() => this.Session.Update(o));
        //    return (T)(INHibernateRepository<T>)this;
        //}

        public T DeleteOnSubmit(object o)
        {
            this.ChangeActions.Add(() => this.Session.Delete(o));
            return (T)(INHibernateRepository<T>)this;
        }

        public void SubmitChanges()
        {
            var actions = this.ChangeActions;
            this.ChangeActions = null;

            using (var tx = this.Session.BeginTransaction())
            {
                foreach (var a in actions) a();
                this.Session.Flush();
                tx.Commit();
            }
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        protected void Dispose(bool disposing)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }

            if (this.m_session != null)
            {
                this.m_session.Dispose();
            }
        }

        ~NHibernateRepository()
        {
            this.Dispose(false);
        }
    }
}
